#ifndef CONNECTOR_H_
#define CONNECTOR_H_

#include <functional>
#include <future>

#include "netlib/base/noncopyable.h"
#include "netlib/net/socket/inet_address.h"

namespace netlib::net {

class EventLoop;
class Channel;

class Connector : NonCopyable {
public:
	using NewConnectionCallback = std::function<void(int)>;

	Connector(EventLoop* loop, const InetAddress& addr);
	~Connector();

	void SetNewConnectionCallback(const NewConnectionCallback& cb) { callback_ = cb; }
	const InetAddress& ServerAddress() const { return server_addr_; }

	void Start();
	bool StartUntil();
	void Restart();
	void Stop();

private:
	void Retry();
	void StartInLoop();
	void StartInLoop(std::promise<void>& pro) {
		StartInLoop();
		pro.set_value();
	}
	void StopInLoop();
	void Connecting(int sockfd);
	int RemoveChannel();
	void DeleteChannel();

	void HandleWrite();
	void HandleError();

	enum State { kDisconnected, kConnecting, kConnected };

	static constexpr int kMaxRetryDelayMs = 30 * 1000;
	static constexpr int kInitRetryDelayMs = 500;

	State state_{kDisconnected};
	bool is_connect_{false};
	EventLoop* loop_;
	InetAddress server_addr_;
	Channel* channel_{nullptr};
	NewConnectionCallback callback_;
	std::promise<bool> connect_promise_;

	int retry_delay_ms_{kInitRetryDelayMs};
};

} // namespace netlib::net

#endif // CONNECTOR_H_